package cn.echo.ecc.service.impl;

import static cn.echo.ecc.constants.MQConstants.*;
import cn.echo.ecc.doc.CourseDoc;
import cn.echo.ecc.domain.*;
import cn.echo.ecc.dto.CourseOnlineSendMessageDto;
import cn.echo.ecc.dto.CourseSaveDto;
import cn.echo.ecc.dto.UserOnlineSendMessageDto;
import cn.echo.ecc.enums.GlobalExceptionCode;
import cn.echo.ecc.feign.CourseESService;
import cn.echo.ecc.feign.MediaFileService;
import cn.echo.ecc.feign.UserService;
import cn.echo.ecc.mapper.CourseMapper;
import cn.echo.ecc.mapper.CourseTypeMapper;
import cn.echo.ecc.result.JSONResult;
import cn.echo.ecc.service.*;
import cn.echo.ecc.util.AssertUtil;
import cn.echo.ecc.vo.CourseDetailVo;
import cn.echo.ecc.vo.CourseInfoVo;
import cn.echo.ecc.vo.CourseOrderVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hulan
 * @since 2022-09-30
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private ITeacherService teacherService;

    @Autowired
    private ICourseMarketService courseMarketService;

    @Autowired
    private CourseTypeMapper courseTypeMapper;

    @Autowired
    private ICourseDetailService courseDetailService;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private ICourseResourceService courseResourceService;

    @Autowired
    private ICourseSummaryService courseSummaryService;

    @Autowired
    private CourseESService courseESService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ICourseCollectService courseCollectService;

    @Autowired
    private UserService userService;

    @Autowired
    private ICourseChapterService courseChapterService;

    @Autowired
    private MediaFileService mediaFileService;

    /**
     * 新增课程
     * @param courseSaveDto
     */
    @Override
    public void save(CourseSaveDto courseSaveDto) {
        // 1.JSR303校验参数不能为空
        // 2.取值
        Course course = courseSaveDto.getCourse();
        CourseDetail courseDetail = courseSaveDto.getCourseDetail();
        CourseMarket courseMarket = courseSaveDto.getCourseMarket();
        CourseResource courseResource = courseSaveDto.getCourseResource();
        List<Long> teacherIds = courseSaveDto.getTeacherIds();
        // 3.业务校验，课程是否已经存在
        Course courseByName = selectCourseByName(course.getName());
        AssertUtil.isNull(courseByName, GlobalExceptionCode.COURSE_EXISTED_ERROR);
        // 4.新增课程
        Long courseId = saveCourse(course,teacherIds);
        // 5.新增课程详情
        saveCourseDetail(courseDetail, courseId);
        // 6.新增课程销售表
        saveCourseMarket(courseMarket,courseId);
        // 7.新增课程资源
        saveCourseResource(courseResource,courseId);
        // 8.新增课程讲师中间表
        courseMapper.saveCourseTeacher(courseId,teacherIds);
        // 9.更改课程类型的课程数量
        courseTypeMapper.updateTotalCountById(course.getCourseTypeId());
        // 9.初始化课程统计表
        initCourseSummary(courseId);
    }

    /**
     * 课程上架
     * @param id
     */
    @Override
    public void onLineCourse(Long id) {
        // 1.校验课程不为空
        Course course = selectById(id);
        AssertUtil.isNotNull(course,GlobalExceptionCode.COURSE_IS_NULL_ERROR);
        // 2.业务校验
        Boolean boo = Course.COURSE_STATUS_ONLINE == course.getStatus();
        AssertUtil.isFalse(boo,GlobalExceptionCode.COURSE_IS_ONLINE_ERROR);
        // 3.修改状态和设置上架时间
        course.setStatus(Course.COURSE_STATUS_ONLINE);
        course.setOnlineTime(new Date());
        updateById(course);
        // 4.调用feign接口，添加到ES
        CourseMarket courseMarket = courseMarketService.selectById(id);
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        CourseSummary courseSummary = courseSummaryService.selectById(id);
        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course,courseDoc);
        BeanUtils.copyProperties(courseMarket,courseDoc);
        BeanUtils.copyProperties(courseSummary,courseDoc);
        courseDoc.setTypeName(courseType.getName());
        String charge = courseMarket.getCharge() == 1 ? "免费" : "收费";
        courseDoc.setCharge(charge);
        JSONResult jsonResult = courseESService.saveCourse(courseDoc);
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobalExceptionCode.FAIL);
        // 5.发送短信、邮件、站内信
        List<CourseCollect> courseCollects = courseCollectService.selectListByTypeName(courseType.getName());
        if (0 != courseCollects.size()) {
            sendSmsMessage(course, courseCollects);
            sendEmailMessage(course, courseCollects);
            sendStationMessage(course, courseCollects);
        }
    }

    /**
     * 课程下架
     * @param id
     */
    @Override
    public void offLineCourse(Long id) {
        // 1.校验课程不为空
        Course course = selectById(id);
        AssertUtil.isNotNull(course,GlobalExceptionCode.COURSE_IS_NULL_ERROR);
        // 2.业务校验
        Boolean boo = Course.COURSE_STATUS_OFFLINE == course.getStatus();
        AssertUtil.isFalse(boo,GlobalExceptionCode.COURSE_IS_OFFLINE_ERROR);
        // 3.修改状态和设置下架时间
        course.setStatus(Course.COURSE_STATUS_OFFLINE);
        updateById(course);
        // 4.调用feign接口，从ES中删除
        courseESService.deleteCourse(id);
    }

    /**
     * 根据courseId获取课程详情
     * @param courseId
     * @return
     */
    @Override
    public CourseDetailVo getCourseDetail(Long courseId) {
        Course course = selectById(courseId);
        // 1.业务校验
        AssertUtil.isNotNull(course,GlobalExceptionCode.USER_NOT_EXISTED_ERROR);
        Boolean boo = course.getStatus() == Course.COURSE_STATUS_ONLINE;
        AssertUtil.isTrue(boo,GlobalExceptionCode.COURSE_IS_OFFLINE_ERROR);
        // 2.封装要返回前端的参数
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        List<CourseChapter> courseChapters = courseChapterService.getCourseChapterByCourseId(courseId);
        List<Teacher> teachers = courseMapper.getTeachersByCourseId(courseId);
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        JSONResult jsonResult = mediaFileService.getMediaFileByCourseId(courseId);
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobalExceptionCode.MEDIA_FILE_IS_NULL_ERROR);
        List<MediaFile> mediaFiles = JSON.parseArray(jsonResult.getData().toString(), MediaFile.class);
        AssertUtil.isNotNull(mediaFiles,GlobalExceptionCode.MEDIA_FILE_IS_NULL_ERROR);
        Map<Long, CourseChapter> map = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        mediaFiles.forEach(e -> {
            e.setFileUrl("");
            CourseChapter courseChapter = map.get(e.getChapterId());
            if (courseChapter != null) {
                courseChapter.getMediaFiles().add(e);
            }
        });
        // 3.创建课程详情对象返回给前端展示
        CourseDetailVo courseDetailVo = new CourseDetailVo(course, courseMarket, courseChapters, teachers, courseDetail, courseSummary);
        return courseDetailVo;
    }

    /**
     * 课程订单确认信息
     * @param courseIds
     * @return
     */
    @Override
    public CourseOrderVo courseOrderInfo(String courseIds) {
        AssertUtil.isNotNull(courseIds,GlobalExceptionCode.PARAM_IS_NOT_BULL);
        // 1.业务校验
        Set<Long> ids = Arrays.stream(courseIds.split(",")).filter(id -> !"".equals(id))
                .map(id -> Long.valueOf(id)).collect(Collectors.toSet());
        Boolean boo = ids.size() == courseIds.split(",").length;
        AssertUtil.isTrue(boo,GlobalExceptionCode.COURSE_REQUEST_PURCHASE_ERROR);
        // 2.查询数据，封装CourseOrderVo
        List<Course> courses = selectBatchIds(ids);
        AssertUtil.isNotNull(courses,GlobalExceptionCode.COURSE_IS_NULL_ERROR);
        Map<Long, CourseMarket> courseMarketMap = courseMarketService.selectBatchIds(ids).stream().collect(Collectors.toMap(CourseMarket::getId, courseMarket -> courseMarket));
        AssertUtil.isNotNull(courseMarketMap,GlobalExceptionCode.COURSE_MARKET_IS_NULL_ERROR);
        List<CourseInfoVo> courseInfoVos = new ArrayList<>();
        CourseOrderVo courseOrderVo = new CourseOrderVo();
        courses.forEach(e -> {
            CourseInfoVo courseInfoVo = new CourseInfoVo();
            Boolean online = e.getStatus() == Course.COURSE_STATUS_OFFLINE;
            AssertUtil.isFalse(online, GlobalExceptionCode.COURSE_IS_OFFLINE_ERROR);
            courseInfoVo.setCourse(e);
            CourseMarket courseMarket = courseMarketMap.get(e.getId());
            AssertUtil.isNotNull(courseMarket,GlobalExceptionCode.COURSE_MARKET_IS_NULL_ERROR);
            courseInfoVo.setCourseMarket(courseMarket);
            courseInfoVos.add(courseInfoVo);
            courseOrderVo.setTotalAmount(courseOrderVo.getTotalAmount().add(courseMarket.getPrice()));
        });
        courseOrderVo.setCourseInfos(courseInfoVos);
        return courseOrderVo;
    }


    /**
     * 发送站内信
     * @param course
     * @param courseCollects
     */
    private void sendStationMessage(Course course,List<CourseCollect> courseCollects) {
        CourseOnlineSendMessageDto courseOnlineSendMessageDto = new CourseOnlineSendMessageDto();
        courseOnlineSendMessageDto.setTitle("课程发布");
        courseOnlineSendMessageDto.setContent("亲爱的用户您好，最新课程 <a href='http://127.0.0.1:6002/list.html?courseTypeId=" + course.getId() +"'> " + course.getName() + " </a> 发布啦，点击课程了解详情");
        List<UserOnlineSendMessageDto> list = new ArrayList<>();
        courseCollects.forEach(e -> {
            UserOnlineSendMessageDto userOnlineSendMessageDto = new UserOnlineSendMessageDto();
            Long userId = e.getUserId();
            userOnlineSendMessageDto.setUserId(userId);
            list.add(userOnlineSendMessageDto);
        });
        courseOnlineSendMessageDto.setUserOnlineSendMessageDtos(list);
        rocketMQTemplate.sendOneWay(COURSE_STATION_TOPIC + ":" + COURSE_STATION_TAG, JSON.toJSONString(courseOnlineSendMessageDto));
    }

    /**
     * 发送邮件
     * @param course
     * @param courseCollects
     */
    private void sendEmailMessage(Course course,List<CourseCollect> courseCollects) {
        CourseOnlineSendMessageDto courseOnlineSendMessageDto = new CourseOnlineSendMessageDto();
        courseOnlineSendMessageDto.setTitle("课程发布");
        courseOnlineSendMessageDto.setContent("亲爱的用户您好，最新课程 <a href='http://127.0.0.1:6002/list.html?courseTypeId=" + course.getId() +"'> " + course.getName() + " </a> 发布啦，点击课程了解详情");
        List<UserOnlineSendMessageDto> list = new ArrayList<>();
        Map<Long, User> map = getUser(courseCollects);
        courseCollects.forEach(e -> {
            UserOnlineSendMessageDto userOnlineSendMessageDto = new UserOnlineSendMessageDto();
            Long userId = e.getUserId();
            userOnlineSendMessageDto.setUserId(userId);
            User user = map.get(userId);
            userOnlineSendMessageDto.setContact(user.getEmail());
            list.add(userOnlineSendMessageDto);
        });
        courseOnlineSendMessageDto.setUserOnlineSendMessageDtos(list);
        rocketMQTemplate.sendOneWay(COURSE_EMAIL_TOPIC + ":" + COURSE_EMAIL_TAG, JSON.toJSONString(courseOnlineSendMessageDto));
    }

    /**
     * 发送短信
     * @param course
     * @param courseCollects
     */
    private void sendSmsMessage(Course course,List<CourseCollect> courseCollects) {
        CourseOnlineSendMessageDto courseOnlineSendMessageDto = new CourseOnlineSendMessageDto();
        courseOnlineSendMessageDto.setTitle("课程发布");
        courseOnlineSendMessageDto.setContent("亲爱的用户您好，最新课程 <a href='http://127.0.0.1:6002/list.html?courseTypeId=" + course.getId() +"'> " + course.getName() + " </a> 发布啦，点击课程了解详情");
        List<UserOnlineSendMessageDto> list = new ArrayList<>();
        Map<Long, User> map = getUser(courseCollects);
        courseCollects.forEach(e -> {
            UserOnlineSendMessageDto userOnlineSendMessageDto = new UserOnlineSendMessageDto();
            Long userId = e.getUserId();
            userOnlineSendMessageDto.setUserId(userId);
            User user = map.get(userId);
            userOnlineSendMessageDto.setContact(user.getPhone());
            list.add(userOnlineSendMessageDto);
        });
        courseOnlineSendMessageDto.setUserOnlineSendMessageDtos(list);
        rocketMQTemplate.sendOneWay(COURSE_SMS_TOPIC + ":" + COURSE_SMS_TAG, JSON.toJSONString(courseOnlineSendMessageDto));
    }

    /**
     * 根据id查询用户
     * @param courseCollects
     * @return
     */
    private Map<Long,User> getUser(List<CourseCollect> courseCollects) {
        List<Long> collect = courseCollects.stream().map(CourseCollect::getUserId).collect(Collectors.toList());
        Object[] ids = collect.toArray();
        JSONResult jsonResult = userService.listUser(ids);
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobalExceptionCode.USER_NOT_EXISTED_ERROR);
        List<User> users = JSON.parseArray(jsonResult.getData().toString(), User.class);
        AssertUtil.isNotNull(users,GlobalExceptionCode.USER_NOT_EXISTED_ERROR);
        Map<Long, User> map = users.stream().collect(Collectors.toMap(User::getId, user -> user));
        return map;
    }

    /**
     * 初始化课程统计表t_course_summary
     * @param courseId
     */
    private void initCourseSummary(Long courseId) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(courseId);
        courseSummaryService.insert(courseSummary);
    }

    /**
     * 新增课程资源t_course_resource
     * @param courseResource
     * @param courseId
     */
    private void saveCourseResource(CourseResource courseResource, Long courseId) {
        courseResource.setCourseId(courseId);
        courseResourceService.insert(courseResource);
    }

    /**
     * 新增课程销售表t_course_market
     * @param courseMarket
     * @param courseId
     */
    private void saveCourseMarket(CourseMarket courseMarket, Long courseId) {
        courseMarket.setId(courseId);
        courseMarketService.insert(courseMarket);
    }

    /**
     * 新增课程详情t_course_detail
     * @param courseDetail
     */
    private void saveCourseDetail(CourseDetail courseDetail, Long courseId) {
        courseDetail.setId(courseId);
        courseDetailService.insert(courseDetail);
    }

    /**
     * 新增课程t_course
     * @param course
     * @param teacherIds
     * @return
     */
    private Long saveCourse(Course course, List<Long> teacherIds) {
        course.setStatus(Course.COURSE_STATUS_OFFLINE);
        course.setStatus(0);
        course.setLoginId(3L);
        course.setLoginUserName("18212125525");
        String teacherName = teacherService.selectBatchIds(teacherIds).stream().map(teacher -> teacher.getName()).collect(Collectors.joining(","));
        course.setTeacherNames(teacherName);
        insert(course);
        return course.getId();
    }

    /**
     * 根据课程名查询课程是否已经存在
     * @param name
     * @return
     */
    private Course selectCourseByName(String name) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name",name);
        return selectOne(wrapper);
    }
}
